﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AzureFileDepot.HelperClasses
{
    public delegate void FileFoundDelegate(FileInfo foundFileInfo, Stream foundFileStream);

    public class FileWatcher
    {
        private FileSystemWatcher fileWatcher;
        private FileFoundDelegate callback; 

        public FileWatcher(string filePath, string fileFilter)
        {
            fileWatcher = new FileSystemWatcher(filePath, fileFilter);
            fileWatcher.Created += new FileSystemEventHandler(WatcherFileNewFile);
        }

        public void Start(FileFoundDelegate callback)
        {
            fileWatcher.EnableRaisingEvents = true;
            this.callback = callback;
        }

        public void Stop()
        {
            // gotta try and remember how to remove an event hanlder
            fileWatcher.EnableRaisingEvents = false;
        }

        void WatcherFileNewFile(object sender, FileSystemEventArgs e)
        {
            Stream newFile = null;

            // #DepotTip
            // we fall into this loop to try and help ensure the file 
            // has been completely written
            // attempt to get exclusive lock on the file
            try
            {
                do
                {
                    Thread.Sleep(500);
                    newFile = GetFileExclusively(e.FullPath);
                    //TODO: should have an end on it, so we don't get stuck in an infinite loop
                    // trying to get the lock on the file
                }
                while (newFile == null);

                this.callback(new FileInfo(e.FullPath), newFile);

                newFile.Close();

            }
            catch (Exception ex)
            {
                //TODO: not good practice, need to trap for specific errors
                // and handle them appropriately 
            }
            finally
            {
                if (newFile != null) newFile.Close();
            }
        }

        private Stream GetFileExclusively(string fullPath)
        {
            Stream stream = null;
            try
            {
                stream = File.Open(fullPath, FileMode.Open, FileAccess.Read, FileShare.None);
            }
            catch (IOException)
            {
                return null;
            }
            return stream;

        }

    }
}
